package performanceReview

import domain.user.AppUser
import org.apache.commons.lang.time.DateFormatUtils

/**
 * Helper class for calculation timelines of performance review form
 */
class TimelineBuilder {
    final static String DEFAULT_DATE_PATTERN = "d.MM.yyyy"

    private int areaWidth
    private int markWidth
    private long minTime
    private long maxTime
    private String datePattern = DEFAULT_DATE_PATTERN;
    private long timeScale = 1.0;


    private TimelineBuilder(int areaWidth, int markWidth, long minTime, long maxTime, long timeScale) {
        this.areaWidth = areaWidth;
        this.markWidth = markWidth;
        this.minTime = minTime;
        this.maxTime = maxTime;
        this.timeScale = timeScale;
    }

    /**
     * Factory method
     */
    public static TimelineBuilder createBuilder(List<AppUser> users, int markWidth, int desiredAreaWidth) {
        def allForms = [] as Set;
        int maxFormsCount = 0;
        users.each {
            Collection publishedForms = Form.findAllByUser(it, [cache:true]).findAll {it.published};
            allForms.addAll(publishedForms);
            maxFormsCount = Math.max(publishedForms.size(), maxFormsCount)
        };
        allForms = allForms.sort {it.modificationDate}
        if (allForms) {
            def minTime = allForms.first().modificationDate.time;
            def maxTime = allForms.last().modificationDate.time;
            def maxAreaWidth = maxFormsCount * markWidth
            def areaWidth = maxAreaWidth > desiredAreaWidth ? maxAreaWidth : desiredAreaWidth;
            long timeScale = 1.0;
            if (maxTime > minTime) {
                timeScale = (maxTime - minTime) / (areaWidth - (maxFormsCount + 0.5) * markWidth);
            }
            return new TimelineBuilder(areaWidth, markWidth, minTime, maxTime, timeScale);
        }
        return null;
    }

    /**
     * Creates timeline model for given forms.
     *  Model is - list of objects [offset, text, formId], where offset is distance after previous PR,
     * text contains date of PR, formId is id of published form
     */
    public List<Map> createTimelineFor(List<Form> publishedForms) {
        ArrayList<Map> timeline = [];
        def lastTime = minTime;
        publishedForms?.sort {it.modificationDate}?.eachWithIndex {form, index ->
            Map timeDefinition = [:]
            long time = form.modificationDate.time;
            timeDefinition.offset = Math.round((time - lastTime) / timeScale);
            timeDefinition.text = DateFormatUtils.format(form.modificationDate, DEFAULT_DATE_PATTERN);
            timeDefinition.formId = form.id;
            timeline.add(timeDefinition);
            lastTime = time;
        }
        return timeline
    }

    /**
     * Returns area with to render timelines generated by this builder instance
     */
    public int getAreaWidth() {
        return areaWidth;
    }
}
